02. Interacting

This tutorial will walk you through our ORM syntax and how to use it to make proper API calls.

Creating a Connection

In each example I'll be assuming that you have configured connection to syncano and you are using ES6 syntax:

import Syncano from 'syncano';

const connection = Syncano({accountKey: 'YOUR_KEY'});
const {Instance, ApiKey} = connection;

Creating objects

A model class represents a single Syncano API endpoint, and an instance of that class represents a particular record in this endpoint.

To create an object, instantiate it using object argument and then call Model.save to save it to the Syncano API.

Here’s an example:

Instance({name: 'test-one', description:''}).save().then((instance) => {
   // your new instance
});

This performs a POST request to Syncano API behind the scenes.
Syncano doesn’t hit the API until you explicitly call Model#save.

Note

To create and save an object in a single step, use the QuerySet#create method.

Saving changes to objects

To save changes to an object that’s already in the Syncano API, use Model#save.
Regarding our instance from previous example, this example changes its description and updates its record in the Syncano API:

instance.description = 'new description'
instance.save().then((updatedInstance) => {
    console.log(updatedInstance.description); // will produce 'new description'
});

This performs a PUT request to Syncano API behind the scenes.
Syncano doesn’t hit the API until you explicitly call Model#save.

Note

To change and save an object in a single step, use the QuerySet#create method.

Retrieving objects

To retrieve objects from Syncano API, construct a query via a QuerySet on your model class.

Each model has only one QuerySet#create, and it’s called please by default.
Access it directly via the model class, like so:

Instance.please()
Note

QuerySet is accessible only via model classes, rather than from model instances,
to enforce a separation between “table-level” operations and “record-level” operations.

Retrieving all objects

The simplest way to retrieve objects from a Syncano API is to get all of them.
To do this, use the QuerySet#list method on a QuerySet:

Instance.please().list().then((instances) => {
    console.log('instances', instances);
});
Note

This performs a GET request to Syncano API list endpoint behind the scenes.

QuerySet is lazy

QuerySet is lazy – the act of creating a QuerySet doesn’t involve any API activity.
You can stack QuerySet methods all day long, and Syncano won’t actually run the API call until the QuerySet is evaluated.
Take a look at this example::

Instance.please().pageSize(1).ordering('desc').then(() => {

});

Though this looks like two API calls, in fact it hits API only once, at the last chain (then).
In general, the results of a QuerySet aren’t fetched from API until you “ask” for them.

Retrieving a single object

If you know there is only one object that matches your API call, you can use the QuerySet#get method on a QuerySet which returns the object directly:

Instance.please().get({name: 'test'}).then((instance) => {

});

This performs a GET request to Syncano API details endpoint behind the scenes. If there are no results that match the API call, QuerySet#get will raise a RequestError exception.

Removing a single object

The delete method, conveniently, is named QuerySet#delete. This method immediately deletes the object and has no return value.

Instance.please().delete({name: 'test'}).then(() => {
});

This performs a DELETE request to Syncano API details endpoint behind the scenes.

Lookups that span relationships

Syncano API has nested architecture so in some cases there will be a need to provide a few additional arguments to resolve endpoint URL.
For example ApiKey model is related to Instance and its URL patter looks like this:

/v1.1/instances/{instance_name}/api_keys/{id}

This example will not work:

ApiKey.please().list().then(() => {}).catch((error) => {
   console.log('error', error);
});

So how to fix that? We need to provide instanceName as an argument to QuerySet#list method:

ApiKey.please().list({instanceName: 'test'}).then((apiKeys) => {
    console.log('apiKeys', apiKeys);
});

This performs a GET request to /v1.1/instances/test/api_keys/.

Backward relations

For example Instance has related ApiKey model so all Instance objects will have backward relation to list of ApiKey's:

Instance.please().get({name: 'test'}).then((instance) => {
    return instance.apiKeys().list();
}).then((apiKeys) => {
    console.log('apiKeys', apiKeys);
});
Note

Related objects do not require additional request properties passed to QuerySet#link method.

Falling back to raw JSON

If you find yourself needing to work on raw JSON data instead of models just use QuerySet#raw method:

Instance.please().list().raw().then((response) => {
    console.log('raw response', response);
});

Pagination

If you find yourself needing to fetch next or previous page of objects just use next or prev method:

Instance.please().list().then((instances) => {
    console.log('first page', instances);
    return instances.next();
}).then((instances) => {
    console.log('second page', instances);
    return instances.prev();
}).then((instances) => {
    console.log('previous / first page', instances);
});